#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>

#define NUM 1024
#define SIZE 100
#define SPA " "

// 保存完整的命令行字符串
char all_order[NUM];
// 保存拆分之后的命令行字符串
char* single_order[SIZE];


// shell 运行原理 ：通过让子进程执行命令，父进程等待&&解析命令
int main()
{
    // 0.命令行解释器，一定是一个常驻内存的进程，不退出
    while(1)
    {
        //1. 打印出提示信息 [dgz@localhost myshell]# 
        printf("[dgz@localhost myshell]# ");
        fflush(stdout);
        memset(all_order,'\0',sizeof all_order);
        //2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]
        if(fgets(all_order,sizeof all_order,stdin) == NULL)
        {
            continue;
        }
        all_order[strlen(all_order) - 1] = '\0';
        // printf("ehco:%s\n",all_order);
        //3. 将获取的命令分割成单个选项， 命令行字符串解析："ls -a -l -i" -> "ls" "-a" "-i"
        single_order[0] = strtok(all_order,SPA);// 第一次调用传入原始字符串
        int index = 1;
        if(strcmp(single_order[0],"ls") == 0)
        {
            single_order[index++] = "--color=auto";
        }
        if(strcmp(single_order[0],"ll") == 0)
        {
            single_order[0] = "ls";
            single_order[1] = "-l";
            single_order[2] = "--color=auto";
        }
        while(single_order[index++] = strtok(NULL,SPA));// 第二次，如果还要解析原字符串，传入NULL
        // for debug
        //for(index = 0;single_order[index];index++)
        //{
        //    printf("single_order[%d]:%s\n",index,single_order[index]);
        //}
        //4. TODO,内置命令，让父进程(shell)自己执行的命令，我们叫做内置命令，内建命令
        //内建命令的本质其实就是shell中的一个函数调用
        if(strcmp(single_order[0],"cd") == 0)// 不是子进程执行，是父进程执行
        {
            if(single_order[0] != NULL)
            {
                chdir(single_order[1]);// cd path cd ..
            }
            continue;
        }
        
        //5.fork
        pid_t id = fork();
        if(id == 0)
        {
            printf("下面为子进程运行的\n");
            execvp(single_order[0],single_order);
            exit(1);
        }
        int status = 0;
        pid_t res = waitpid(-1,&status,0);
        if(res > 0)
        {
            printf("exit code: %d\n",WEXITSTATUS(status));
        }
    }

    return 0;
}



